import React, { useReducer } from 'react';
import type { AnyObject, Column, Errors, Size, Sort } from '../type';
import {
  ColumnPinning,
  CurOperateInfo,
  TablePagination,
  ValidateError,
} from '../type';

interface Props {
  children: React.ReactNode;
  context?: React.Context<any>;
}

interface Action {
  type: string;
  payload: any;
}
export interface ScrollInfo {
  scrollLeft: number;
  scrollTop: number;
  clientWidth: number;
  clientHeight: number;
  scrollWidth: number;
  scrollHeight: number;
}
// 编辑表格的table Context 数据
export interface TableContext<T extends AnyObject> {
  id?: string;
  name?: string;
  isCanEdit?: boolean;
  isShowPopModal?: boolean;
  size?: Size;
  errors?: Errors<T>;
  curOperateInfo?: CurOperateInfo<T>;
  widths?: AnyObject;
  style: React.CSSProperties;
  scroll: ScrollInfo;
  /** 显示的列 */
  columns: Column<T>[];
  dataSource: T[];
  /** 固定的列 */
  columnPinning: ColumnPinning;
  pagination: TablePagination;
  columnSorting: { [columnId in string]?: Sort };
}
type TableAction = Action;
export interface Context<T extends AnyObject> {
  table: TableContext<T>;
  dispatch: React.Dispatch<TableAction>;
}
export const initScrollInfo: ScrollInfo = {
  scrollTop: 0,
  scrollLeft: 0,
  clientWidth: 0,
  clientHeight: 0,
  scrollWidth: 0,
  scrollHeight: 0,
};
export const initTableContext: TableContext<any> = {
  id: '',
  name: '',
  isCanEdit: false,
  isShowPopModal: false,
  size: 'large',
  errors: [],
  curOperateInfo: {
    rowIndex: -1,
    columnId: '',
    data: {},
    meta: {},
    curValue: '',
  },
  style: {},
  widths: {},
  scroll: { ...initScrollInfo },
  columns: [],
  dataSource: [],
  columnPinning: { left: [], right: [] },
  pagination: false,
  columnSorting: {},
};
export const UPDATE_STATE = 'UPDATE_STATE';
export const UPDATE_Id = 'UPDATE_Id';
export const UPDATE_NAME = 'UPDATE_NAME';
export const UPDATE_ISCANEDIT = 'UPDATE_ISCANEDIT';
export const UPDATE_ISSHOWPOPMODAL = 'UPDATE_ISSHOWPOPMODAL';
export const UPDATE_SIZE = 'UPDATE_SIZE';
export const UPDATE_ERRORS = 'UPDATE_ERRORS';
export const UPDATE_CUROPERATEINFO = 'UPDATE_CUROPERATEINFO';
export const UPDATE_STYLE = 'UPDATE_STYLE';
export const UPDATE_SCROLL = 'UPDATE_SCROLL';
export const UPDATE_COLUMNS = 'UPDATE_COLUMNS';
export const UPDATE_DATASOURCE = 'UPDATE_DATASOURCE';
export const UPDATE_COLUMNPINNING = 'UPDATE_COLUMNPINNING';
export const UPDATE_PAGINATION = 'UPDATE_PAGINATION';
export const UPDATE_COLUMNSORTING = 'UPDATE_COLUMNSORTING';

export const updateErrors: <T extends AnyObject>(
  index: number,
  updateError: ValidateError<T>,
  originalError: Errors<T>,
) => Errors<T> = (index, updateError, originalError) => {
  originalError[index] = updateError;
  return originalError;
};

export const tableReducer = (state: TableContext<any>, action: TableAction) => {
  switch (action.type) {
    case UPDATE_STATE:
      return {
        ...state,
        ...action.payload,
      };
    case UPDATE_Id:
      return {
        ...state,
        id: action.payload,
      };
    case UPDATE_NAME:
      return {
        ...state,
        name: action.payload,
      };
    case UPDATE_ISCANEDIT:
      return {
        ...state,
        isCanEdit: action.payload,
      };
    case UPDATE_ISSHOWPOPMODAL:
      return {
        ...state,
        isShowPopModal: action.payload,
      };
    case UPDATE_SIZE:
      return {
        ...state,
        size: action.payload,
      };
    case UPDATE_ERRORS:
      return {
        ...state,
        errors: action.payload,
      };
    case UPDATE_CUROPERATEINFO:
      return {
        ...state,
        curOperateInfo: action.payload,
      };
    case UPDATE_STYLE:
      return {
        ...state,
        style: action.payload,
      };
    case UPDATE_SCROLL:
      return {
        ...state,
        scroll: action.payload,
      };
    case UPDATE_COLUMNS:
      return {
        ...state,
        columns: action.payload,
      };
    case UPDATE_DATASOURCE:
      return {
        ...state,
        dataSource: action.payload,
      };
    case UPDATE_COLUMNPINNING:
      return {
        ...state,
        columnPinning: action.payload,
      };
    case UPDATE_PAGINATION:
      return {
        ...state,
        pagination: action.payload,
      };
    case UPDATE_COLUMNSORTING:
      return {
        ...state,
        columnSorting: action.payload,
      };

    default:
      return initTableContext;
  }
};

/*
 * 此文件为从基础表格衍生的各种表格所使用的 table context
 * 各表格使用该context 存储表格信息步骤
 * 1. 调用 createContext 方法创建 context
 * 2. TableContext 传入创建的 context
 * 3. 基础表格 DisplayTable 传入创建的 context
 */
export const createContext = () => {
  return React.createContext<Context<any>>({
    table: initTableContext,
    dispatch: () => {},
  });
};
export const tableContext: any = createContext();

function TableContext(props: Props) {
  const context = props.context || tableContext;
  const [table, dispatch] = useReducer(tableReducer, initTableContext);
  return (
    <context.Provider value={{ table, dispatch }}>
      {props.children}
    </context.Provider>
  );
}

export default TableContext;
